package com.mycase.im.boot.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mycase.im.boot.security.CustomUsernamePasswordAuthenticationFilter;
import com.mycase.im.boot.entity.communication.ResponseMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @Author ZhuHJay
 * @Date 2021/8/4 11:03
 */
@Configuration
@Slf4j
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private UserDetailsService userDetailsService;
    private CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter;
    private ObjectMapper objectMapper = new ObjectMapper();

    SecurityConfiguration(UserDetailsService userDetailsService,
                          CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter){
        this.userDetailsService = userDetailsService;
        this.customUsernamePasswordAuthenticationFilter = customUsernamePasswordAuthenticationFilter;
    }

    /** 加密 **/
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /** 设置身份认证管理器, 不配会报错 **/
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    /** 核心配置: 创建过滤器链 **/
    @Override
    public void configure(WebSecurity webSecurity){
        // 放行 WebSocket连接
        webSecurity.ignoring().antMatchers(
                "/ws/**",
                "/api/**",
                "/druid/**",
                "/static/**"
        );
    }

    /** 核心配置: 配置过滤器链 **/
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // 设置跨域
            .cors().and()
            // 关闭 csrf 安全
            .csrf().disable();

        http.userDetailsService(userDetailsService);

        // 设置拦截器
        http.addFilterBefore(customUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        // 设置请求拦截
        http.authorizeRequests()
                // 登录请求路径不进行过滤
                .antMatchers("/login", "/register", "/static/**").permitAll()
                .antMatchers("/api/**").hasRole("USER")
                .anyRequest()
                .authenticated();

        http.formLogin().usernameParameter("username").passwordParameter("password").loginProcessingUrl("/login");

        // 退出登录(注销)
        http.logout()
                // 注销成功的处理器
                .logoutSuccessHandler(((request, response, authentication) -> {
                    String message;
                    log.warn("当前账号注销成功");
                    message = objectMapper.writeValueAsString(ResponseMessage.success("退出成功"));
                    response.setContentType("application/json;charset=utf-8");
                    response.setCharacterEncoding("utf-8");
                    response.getOutputStream().write(message.getBytes());
                }));
    }

}
